﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using TPG.SharePoint.Workflow.Controls.Design;
using Microsoft.SharePoint.Utilities;
using System.Drawing;

namespace TPG.SharePoint.Workflow.Controls
{
    [Designer(typeof(InputFormSectionDesigner)),
    ToolboxData("<{0}:InputFormSection runat=\"server\"></{0}:InputFormSection>")]
    public class InputFormSection
        : FormSection
    {
        ITemplate _titleTemplate;
        ITemplate _descriptionTemplate;
        ITemplate _contentTemplate;
        WebControl _titleTemplateContainer;
        TableCell _descriptionTemplateContainer;
        ContentContainer _contentTemplateContainer;
        TableRow _contentTablePaddingRow;
        TableRow _titleTablePaddingRow;
        TableCell _contentTableTopPaddingCell;

        [DefaultValue(""),
        Category("Appearance"),
        Description("The title of the section.")]
        public string Title
        {
            get { return (string)ViewState["Title"] ?? String.Empty; }
            set { ViewState["Title"] = value; }
        }

        [DefaultValue(""),
        Category("Appearance"),
        Description("A descriptive text detailing the section's purpose.")]
        public string Description
        {
            get { return (string)ViewState["Description"] ?? String.Empty; }
            set { ViewState["Description"] = value; }
        }

        public bool Padding
        {
            get { return (bool?)ViewState["Padding"] ?? true; }
            set 
            {
                if (value != Padding)
                {
                    ViewState["Padding"] = value;
                    if (ChildControlsCreated)
                    {
                        ApplyPaddingProperties();
                    }
                }
            }
        }

        [PersistenceMode(PersistenceMode.InnerProperty),
        TemplateContainer(typeof(InputFormSection)),
        TemplateInstance(TemplateInstance.Single),
        DefaultValue(null),
        Browsable(false)]
        public ITemplate TitleTemplate
        {
            get { return _titleTemplate; }
            set
            {
                _titleTemplate = value;
                _titleTemplateContainer = null;
                ChildControlsCreated = false;
            }
        }

        [PersistenceMode(PersistenceMode.InnerProperty),
        TemplateContainer(typeof(InputFormSection)),
        TemplateInstance(TemplateInstance.Single),
        DefaultValue(null),
        Browsable(false)]
        public ITemplate DescriptionTemplate
        {
            get { return _descriptionTemplate; }
            set
            {
                _descriptionTemplate = value;
                _descriptionTemplateContainer = null;
                ChildControlsCreated = false;
            }
        }

        [PersistenceMode(PersistenceMode.InnerProperty),
        TemplateContainer(typeof(InputFormSection)),
        TemplateInstance(TemplateInstance.Single),
        DefaultValue(null),
        Browsable(false)]
        public ITemplate ContentTemplate
        {
            get { return _contentTemplate; }
            set
            {
                _contentTemplate = value;
                _contentTemplateContainer = null;
                ChildControlsCreated = false;
            }
        }

        public override ControlCollection Controls
        {
            get
            {
                EnsureChildControls();
                return base.Controls;
            }
        }

        protected override void OnInit(EventArgs e)
        {
            EnsureChildControls();
            base.OnInit(e);
        }

        protected override void CreateChildControls()
        {
            Controls.Clear();
            Controls.Add(CreateOuterTableTopRow());
            Controls.Add(CreateOuterTableBottomRow());
            ChildControlsCreated = true;
            ClearChildViewState();
        }

        protected override void Render(HtmlTextWriter writer)
        {
            RenderChildren(writer);
        }

        protected override IDictionary GetDesignModeState()
        {
            IDictionary state = base.GetDesignModeState();
            state["TitleTemplateContainer"] = _titleTemplateContainer;
            state["DescriptionTemplateContainer"] = _descriptionTemplateContainer;
            state["ContentTemplateContainer"] = _contentTemplateContainer;
            return state;
        }


        TableRow CreateOuterTableTopRow()
        {
            TableRow topSpacerRow = new TableRow();
            topSpacerRow.ID = SPHttpUtility.NoEncode(ClientID) + "_tablerow1";
            TableCell topSpacerCell = new TableCell();
            topSpacerRow.Cells.Add(topSpacerCell);
            topSpacerCell.CssClass = "ms-sectionline";
            topSpacerCell.ColumnSpan = 2;
            topSpacerCell.Height = new Unit(1);
            topSpacerCell.Controls.Add(new Spacer(1, 1));
            return topSpacerRow;
        }

        TableRow CreateOuterTableBottomRow()
        {
            TableRow row = new TableRow();
            TableCell firstCell = new TableCell();
            TableCell secondCell = new TableCell();
            row.Cells.AddRange(new TableCell[] { firstCell, secondCell });
            firstCell.Controls.Add(CreateTitleTable());
            secondCell.Controls.Add(CreateContentTable());
            row.ID = SPHttpUtility.NoEncode(ClientID);
            firstCell.CssClass = "ms-descriptiontext";
            firstCell.VerticalAlign = VerticalAlign.Top;
            secondCell.CssClass = "ms-authoringcontrols ms-inputformcontrols";
            secondCell.VerticalAlign = VerticalAlign.Top;
            secondCell.HorizontalAlign = HorizontalAlign.Left;
            return row;
        }

        Control CreateTitleTable()
        {
            Table table = new Table();
            table.Rows.Add(CreateTitleRow());
            table.Rows.Add(CreateDescriptionRow());
            _titleTablePaddingRow = CreateSpacerRow(150, 19);
            table.Rows.Add(_titleTablePaddingRow);
            table.CellPadding = 1;
            table.CellSpacing = 0;
            table.Width = Unit.Percentage(100);
            return table;
        }

        private static TableRow CreateSpacerRow(int width, int height)
        {
            TableRow spacerRow = new TableRow();
            TableCell spacerCell = new TableCell();
            Spacer spacer = new Spacer(width, height);
            spacerCell.Controls.Add(spacer);
            spacerRow.Controls.Add(spacerCell);
            return spacerRow;
        }

        TableRow CreateTitleRow()
        {
            TableRow titleRow = new TableRow();
            TableCell titleCell = new TableCell();

            if (_titleTemplateContainer == null)
            {
                _titleTemplateContainer = new WebControl(HtmlTextWriterTag.H3);
                ITemplate titleTemplate = _titleTemplate ?? new DefaultTitleTemplate(this);
                titleTemplate.InstantiateIn(_titleTemplateContainer);
                _titleTemplateContainer.CssClass = "ms-standardheader";
            }
            titleRow.Cells.Add(titleCell);
            titleCell.Controls.Add(_titleTemplateContainer);
            titleCell.CssClass = "ms-sectionheader";
            titleCell.Style[HtmlTextWriterStyle.PaddingTop] = "4px";
            titleCell.Height = new Unit(22);
            titleCell.VerticalAlign = VerticalAlign.Top;
            return titleRow;
        }

        TableRow CreateDescriptionRow()
        {
            TableRow descriptionRow = new TableRow();
            if (_descriptionTemplateContainer == null)
            {
                _descriptionTemplateContainer = new TableCell();
                ITemplate descriptionTemplate = _descriptionTemplate ?? new DefaultDescriptionTemplate(this);
                descriptionTemplate.InstantiateIn(_descriptionTemplateContainer);
                _descriptionTemplateContainer.CssClass = "ms-descriptiontext ms-inputformdescription";
            }
            TableCell descriptionSecondCell = new TableCell();
            descriptionSecondCell.Controls.Add(new Spacer(8, 1));

            descriptionRow.Cells.AddRange(new TableCell[] { _descriptionTemplateContainer, descriptionSecondCell });
            return descriptionRow;
        }

        Control CreateContentTable()
        {
            Table table = new Table();
            table.Rows.Add(CreateTopContentTableRow());
            table.Rows.Add(CreateBottomContentTableRow());
            _contentTablePaddingRow = new TableRow();
            _contentTablePaddingRow.Cells.Add(new TableCell());
            _contentTablePaddingRow.Cells.Add(new TableCell());
            _contentTablePaddingRow.Cells.Add(new TableCell());
            _contentTablePaddingRow.Cells[1].Controls.Add(new Spacer(150, 13));
            table.Rows.Add(_contentTablePaddingRow);
            table.CellSpacing = 0;
            table.CellPadding = 0;
            table.Width = Unit.Percentage(100);
            ApplyPaddingProperties();
            return table;
        }


        TableRow CreateTopContentTableRow()
        {
            TableRow row = new TableRow();
            TableCell firstCell = new TableCell();
            row.Cells.Add(firstCell);
            firstCell.Controls.Add(new Spacer(9, 7));
            firstCell.Width = Unit.Pixel(9);

            _contentTableTopPaddingCell = new TableCell();
            _contentTableTopPaddingCell.Controls.Add(new Spacer(150, 7));
            row.Cells.Add(_contentTableTopPaddingCell);
            TableCell thirdCell = new TableCell();
            thirdCell.Controls.Add(new Spacer(10, 1));
            thirdCell.Width = Unit.Pixel(10);
            row.Cells.Add(thirdCell);
            return row;
        }

        TableRow CreateBottomContentTableRow()
        {
            TableRow row = new TableRow();
            TableCell firstCell = new TableCell();
            TableCell secondCell = new TableCell();
            TableCell thirdCell = new TableCell();
            if (_contentTemplateContainer == null)
            {
                _contentTemplateContainer = new ContentContainer();
                if (_contentTemplate != null)
                {
                    _contentTemplate.InstantiateIn(_contentTemplateContainer);
                }
                _contentTemplateContainer.CssClass = "ms-authoringcontrols";
                _contentTemplateContainer.Width = Unit.Percentage(100);
                _contentTemplateContainer.CellPadding = 0;
                _contentTemplateContainer.CellSpacing = 0;
            }

            row.Cells.AddRange(new TableCell[] { firstCell, secondCell, thirdCell });
            thirdCell.Controls.Add(new Spacer(10, 1));
            thirdCell.Width = Unit.Pixel(10);
            secondCell.CssClass = "ms-authoringcontrols";

            secondCell.Controls.Add(_contentTemplateContainer);
            return row;
        }

        void ApplyPaddingProperties()
        {
            _contentTablePaddingRow.Visible = Padding;
            _titleTablePaddingRow.Visible = Padding;
            _contentTableTopPaddingCell.Visible = Padding;
        }

        class ContentContainer
            : WebControl
        {
            protected override HtmlTextWriterTag TagKey
            {
                get { return HtmlTextWriterTag.Table; }
            }
            [DefaultValue(-1),
            Category("Appearance")]
            public int CellSpacing
            {
                get
                {
                    if (ControlStyleCreated == false)
                    {
                        return -1;
                    }
                    return ((TableStyle)ControlStyle).CellSpacing;
                }
                set
                {
                    ((TableStyle)ControlStyle).CellSpacing = value;
                }
            }

            [DefaultValue(-1),
            Category("Appearance")]
            public int CellPadding
            {
                get
                {
                    if (ControlStyleCreated == false)
                    {
                        return -1;
                    }
                    return ((TableStyle)ControlStyle).CellPadding;
                }
                set
                {
                    ((TableStyle)ControlStyle).CellPadding = value;
                }
            }
            protected override Style CreateControlStyle()
            {
                return new TableStyle(ViewState);
            }

            class ContentContainerControlCollection
                : ControlCollection
            {
                public ContentContainerControlCollection(ContentContainer owner)
                    : base(owner)
                {
                }

                public override void Add(Control child)
                {
                    ValidateCell(child);
                    base.Add(child);
                }

                public override void AddAt(int index, Control child)
                {
                    ValidateCell(child);
                    base.AddAt(index, child);
                }

                private static void ValidateCell(Control child)
                {
                    InputFormControl cell = child as InputFormControl;
                    if (cell == null)
                    {
                        throw new ArgumentException();
                    }
                }
            }
        }

        class DefaultTitleTemplate
            : ITemplate
        {
            InputFormSection _owner;
            LiteralControl _literal;

            public DefaultTitleTemplate(InputFormSection owner)
            {
                _owner = owner;
                _owner.PreRender += new EventHandler(Owner_PreRender);
            }

            public void InstantiateIn(Control container)
            {
                string title = _owner.Title;
                if (String.IsNullOrEmpty(title) && _owner.DesignMode)
                {
                    title = "[Title]";
                }
                _literal = new LiteralControl(title);
                container.Controls.Add(_literal);
            }

            void Owner_PreRender(object sender, EventArgs e)
            {
                _literal.Text = _owner.Title;
            }
        }

        class DefaultDescriptionTemplate
            : ITemplate
        {
            InputFormSection _owner;
            LiteralControl _literal;

            public DefaultDescriptionTemplate(InputFormSection owner)
            {
                _owner = owner;
                _owner.PreRender += new EventHandler(Owner_PreRender);
            }

            public void InstantiateIn(Control container)
            {
                string description = _owner.Description;
                if (String.IsNullOrEmpty(description) && _owner.DesignMode)
                {
                    description = "[Description]";
                }
                _literal = new LiteralControl(description);
                container.Controls.Add(_literal);
            }

            void Owner_PreRender(object sender, EventArgs e)
            {
                _literal.Text = _owner.Description;
            }
        }
    }
}
